function say(o: object | number | string): void {
  console.log(typeof o, ":", o);
}

//
// 解构
//
interface io {
  n: number;
}

// 使用接口指定类型
const o: io = { n: 1 };
// 解构缩写
const { n } = o;
// 解构
const { n: _n1 } = o;
// 直接解构
const _n2: number = o.n;

[o, n, _n1, _n2].forEach((c: object | number): void => say(c));

// 直接指定类型
const o2: { n2: number } = { n2: 2 };
const { n2 } = o2;

[o2, n2].forEach((c: object | number): void => say(c));

//
// 部分解构
//
const a: number[] = [1, 2, 3, 4, 5];
const [i0, , i1, ...rest] = a;
const m = new Map<string, string>([
  ["k1", "v1"],
  ["k2", "v2"],
]);
// 部分解构元素
for (const [, v] of m) {
  say(v);
}
// 大多数场景下相当于
m.forEach((v: string): void => say(v));

[a, i0, i1, rest].forEach((c: number[] | number): void => say(c));

//
// 扩展操作符 ...
//
const m2 = new Map<string, string>([...m, ...new Map<string, string>([["k3", "v3"]])]);
const o3: { n3: number } = { n3: 3 };
const o4 = { ...o3, ...({ n4: 4 } as { n4: number }) };
const aa: number[] = [1, 2, 3];
const aaa: number[] = [...aa, ...[4, 5], 6, 7];

[m2, o3, o4, aa, aaa, ...aa].forEach((c: (() => void) | Map<string, string> | number | object): void => say(c));

//
// 构造
//
const f: () => void = (): void => console.log("f");
// 构造缩写
const o5: object = { f };
// 构造
const o6: object = { f: f };
// 构造缩写
const o7: object = {
  f(): void {
    console.log("f");
  },
};
// 构造
const o8 = {
  f: function f(): void {
    console.log("f");
  },
};
// 构造
const o9: object = { f: (): void => console.log("f") };

[f, o5, o6, o7, o8, o9].forEach((c: (() => void) | object): void => say(c));

export {};
